///\todo upgrade

//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2012 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#ifndef _BUOLA_IO_SCHEME_FILE_H_
#define _BUOLA_IO_SCHEME_FILE_H_

#include <buola/buola.h>
#include <buola/io/curischeme.h>
#include <buola/io/cfileimpl.h>
#include <buola/io/cfdstream.h>

#include <sys/stat.h>

namespace buola { namespace io {

///\addtogroup filesystem
///@{

////////////////////////////////////////////////////////////////////////////

/// URI scheme for the local filesystem (file:)

///
///
///
////////////////////////////////////////////////////////////////////////////

class CFileScheme : public CURIScheme
{
public:
    CFileScheme();
    virtual ~CFileScheme();

    ///returns a file object to access the given URI
    virtual CFileImpl *GetFileImpl(const CURI &pURI);

    virtual std::string GetRelativeTo(const CURI &pOne,const CURI &pTo);
    virtual void CreateFolder(const CURI &pURI,bool pParents);

    virtual void NormalizeURI(CURI &pURI);
    virtual void CanonicalizeURI(CURI &pURI);

    virtual bool Exists(const CURI &pURI);
    virtual bool IsRegular(const CURI &pURI);
    virtual bool IsFolder(const CURI &pURI);
};

class CFileFileImpl : public CFileImpl
{
public:
    CFileFileImpl(const CURI &pURI);

    virtual CURI GetTarget();
    
    virtual CCalendarTime GetAccessTime();
    virtual CCalendarTime GetCreationTime();
    virtual CCalendarTime GetModificationTime();

    virtual EFileType GetType();

    virtual ssize_t GetSize();

    virtual os::CUser GetOwner();
    virtual os::CGroup GetGroup();

    virtual EPermission GetPermission();

    ///true if the current user can read the file
    virtual bool CanRead();
    ///true if the current user can write to the file
    virtual bool CanWrite();
    ///true if the current user can execute the file
    virtual bool CanExecute();

    ///true if the current user can change ownership of the file
    virtual bool CanChangeOwner();
    ///true if the current user can change group of the file
    virtual bool CanChangeGroup();
    ///true if the current user can change permissions for the file
    virtual bool CanChangePermissions();

    ///returns a vector with all children of this file (if the file is a folder)
    virtual std::vector<CFile> GetChildren(PFileFilter pFilter=nullptr);

    ///returns a stream to the file
    PStream GetStream(io::EMode pMode,io::EPermission pPermission) override;

private:
    void RetrieveInfo();
    
    bool mHasInfo;
    struct stat mInfo;
};

///@}

/*namespace io*/ } /*namespace buola*/ }

#endif
